<script setup lang="ts">
// 导入Vue相关功能
import { computed, watch } from 'vue'

// 定义组件的属性接口
interface DrawerProps {
  // 控制抽屉是否显示
  visible: boolean
  // 抽屉弹出方向：左、右、上、下
  placement?: 'left' | 'right' | 'top' | 'bottom'
  // 过渡动画类型，支持预定义值和自定义字符串 transition: transform .5s cubic-bezier(.32, .72, 0, 1);
  transition?: 'ease' | 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | string
  // 过渡动画持续时间（毫秒）
  duration?: number
  // 抽屉的厚度（宽度或高度，根据方向而定）
  thickness?: string | number
  // 是否显示遮罩层
  mask?: boolean
  // 点击遮罩层是否可以关闭抽屉
  maskClosable?: boolean
  // 是否显示关闭按钮
  closable?: boolean
  // 抽屉标题
  title?: string
}

// 定义组件属性的默认值和类型
const props = withDefaults(defineProps<DrawerProps>(), {
  visible: false,
  placement: 'right',
  transition: 'ease',
  duration: 300,
  thickness: 300,
  mask: true,
  maskClosable: true,
  closable: true,
  title: '抽屉标题'
})

// 定义组件发出的事件
interface DrawerEmits {
  // 关闭事件
  (e: 'close'): void
  // 更新visible状态事件
  (e: 'update:visible', visible: boolean): void
}

// 定义组件发出的事件
const emit = defineEmits<DrawerEmits>()

// 计算抽屉的样式
const drawerStyle = computed(() => {
  // 根据方向确定厚度的单位（left/right用width，top/bottom用height）
  const sizeProperty =
      props.placement === 'left' || props.placement === 'right'
          ? 'width'
          : 'height'

  // 处理厚度值，如果是数字则添加px单位
  const thicknessValue =
      typeof props.thickness === 'number'
          ? `${props.thickness}px`
          : props.thickness

  // 返回样式对象
  return {
    [sizeProperty]: thicknessValue,
    // 设置过渡动画
    transition: `transform ${props.duration}ms ${props.transition}`
  }
})

// 关闭抽屉的方法
const close = () => {
  // 发出关闭事件
  emit('close')
  // 更新visible状态
  emit('update:visible', false)
}

// 处理遮罩层点击事件
const handleMaskClick = () => {
  // 只有在允许点击遮罩关闭时才执行关闭操作
  if (props.maskClosable) {
    close()
  }
}

// 监听visible属性变化，处理body滚动锁定
watch(
    () => props.visible,
    (newVal) => {
      if (newVal) {
        // 抽屉打开时禁止页面滚动
        document.body.style.overflow = 'hidden'
      } else {
        // 抽屉关闭时恢复页面滚动
        document.body.style.overflow = ''
      }
    },
    { immediate: true }
)
</script>

<template>
  <!-- 抽屉组件模板 -->
  <div class="drawer-wrapper">
    <!-- 遮罩层，只有在显示遮罩层时才渲染 -->
    <div
        v-if="mask"
        class="drawer-mask"
        :class="{ 'drawer-mask-show': visible }"
        @click="handleMaskClick"
    ></div>

    <!-- 抽屉容器 -->
    <div
        class="drawer"
        :class="[
        `drawer-${placement}`,  // 根据方向添加对应的类名
        { 'drawer-open': visible }  // 根据显示状态添加打开类名
      ]"
        :style="drawerStyle"  // 应用动态样式
    >
    <!-- 抽屉头部 -->
    <div class="drawer-header">
      <slot name="header">
        <div class="drawer-title">{{ title }}</div>
      </slot>
      <!-- 关闭按钮 -->
      <button
          v-if="closable"
          class="drawer-close"
          @click="close"
      >
        ×
      </button>
    </div>

    <!-- 抽屉内容区域 -->
    <div class="drawer-content">
      <slot></slot>
    </div>
  </div>
  </div>
</template>

<style scoped lang="scss">
// 抽屉组件样式

// 基础变量定义
$drawer-z-index: 1000;
$drawer-bg-color: #ffffff;
$drawer-border-color: #e8e8e8;
$drawer-header-height: 50px;

// 抽屉包装器
.drawer-wrapper {
  // 确保定位上下文正确
  position: relative;
}

// 遮罩层样式
.drawer-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: $drawer-z-index;
  // 初始状态透明
  opacity: 0;
  visibility: hidden;
  will-change: opacity, visibility;
  // 过渡动画
  transition: opacity 0.3s ease, visibility 0.3s ease;

  // 遮罩层显示状态
  &.drawer-mask-show {
    opacity: 1;
    visibility: visible;
  }
}

// 抽屉容器基础样式
.drawer {
  position: fixed;
  background: $drawer-bg-color;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: $drawer-z-index + 1;
  will-change: transform;
  transition: transform .5s cubic-bezier(.32, .72, 0, 1);

  // 默认设置为右侧抽屉
  top: 0;
  right: 0;
  width: 300px;
  height: 100%;
  // 初始状态在屏幕外
  transform: translateX(100%);

  // 左侧抽屉
  &.drawer-left {
    left: 0;
    right: auto;
    transform: translateX(-100%);

    // 打开状态
    &.drawer-open {
      transform: translateX(0);
    }
  }

  // 右侧抽屉
  &.drawer-right {
    right: 0;
    left: auto;
    transform: translateX(100%);

    // 打开状态
    &.drawer-open {
      transform: translateX(0);
    }
  }

  // 顶部抽屉
  &.drawer-top {
    top: 0;
    left: 0;
    width: 100%;
    height: 300px;
    transform: translateY(-100%);

    // 打开状态
    &.drawer-open {
      transform: translateY(0);
    }
  }

  // 底部抽屉
  &.drawer-bottom {
    bottom: 0;
    top: auto;
    left: 0;
    width: 100%;
    height: 300px;
    transform: translateY(100%);

    // 打开状态
    &.drawer-open {
      transform: translateY(0);
    }
  }
}

// 抽屉头部样式
.drawer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: $drawer-header-height;
  padding: 0 20px;
  border-bottom: 1px solid $drawer-border-color;
  background: $drawer-bg-color;
}

// 抽屉标题样式
.drawer-title {
  font-size: 16px;
  font-weight: 500;
  color: #333;
}

// 抽屉关闭按钮样式
.drawer-close {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  color: #999;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s ease, color 0.3s ease;

  // 鼠标悬浮时旋转效果
  &:hover {
    transform: rotate(90deg);
    color: #333;
  }
}

// 抽屉内容区域样式
.drawer-content {
  height: calc(100% - #{$drawer-header-height});
  overflow-y: auto;
  padding: 20px;
}
</style>